﻿using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml.Serialization;

namespace CustomerAssistant.Core
{
    public class Util
    {
        public static readonly object SyncRoot = new object();
        /// <summary>
        /// 分辨请求的key,用于分发到对应的处理程序
        /// </summary>
        public readonly static string REQUEST_KEY = "handle";
        public readonly static string CLIENTHANDLECHAIN_KEY = "IClientHandleChain";

        /// <summary>
        /// 请求处理职责链头部
        /// </summary>
        public static IClientHandle ClientHandleHeader
        {
            get
            {
                return (IClientHandle)HttpContext.Current.Application[CLIENTHANDLECHAIN_KEY];
            }
        }

        public static string Serialize<T>(T t)
        {
            using (StringWriter sw = new StringWriter())
            {
                XmlSerializer xz = new XmlSerializer(typeof(T));
                xz.Serialize(sw, t);
                return sw.ToString();
            }
        }

        public static T Deserialize<T>(string xmlstr) where T : class
        {
            using (StringReader sr = new StringReader(xmlstr))
            {
                XmlSerializer xs = new XmlSerializer(typeof(T));
                return xs.Deserialize(sr) as T;
            }
        }

        /// <summary>
        /// http请求
        /// </summary>
        /// <param name="requestData">用&分隔的标准请求数据</param>
        /// <returns></returns>
        public static void HttpRequest(string url, string requestData, Action<string> callback)
        {
            #region 构造请求

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
            request.Timeout = 10000;//10秒超时
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.BeginGetRequestStream(new AsyncCallback((asyncresult) =>
            {
                var req = (HttpWebRequest)asyncresult.AsyncState;
                Stream postStream = req.EndGetRequestStream(asyncresult);
                byte[] byteData = Encoding.ASCII.GetBytes(requestData);
                postStream.Write(byteData, 0, byteData.Length);//写入请求流
                postStream.Flush();
                postStream.Close();

                HttpWebResponse Response = (HttpWebResponse)request.GetResponse();//响应对象
                Stream responseStream = Response.GetResponseStream();//响应流
                StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                var result = reader.ReadToEnd();
                reader.Close();
                callback(result);
            }), request);

            #endregion 构造请求
        }

        /// <summary>
        /// http请求
        /// </summary>
        /// <param name="requestData">用&分隔的标准请求数据</param>
        /// <returns></returns>
        public static string HttpRequest(string url, string requestData)
        {
            #region 构造请求

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
            request.Timeout = 10000;//10秒超时
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            Stream requestStream = request.GetRequestStream();
            byte[] byteData = Encoding.ASCII.GetBytes(requestData);
            requestStream.Write(byteData, 0, byteData.Length);//写入请求流
            requestStream.Flush();
            requestStream.Close();

            #endregion 构造请求

            #region 响应且输出

            HttpWebResponse Response = (HttpWebResponse)request.GetResponse();//响应对象
            Stream responseStream = Response.GetResponseStream();//响应流
            StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);

            #endregion 响应且输出

            var result = reader.ReadToEnd();
            reader.Close();
            return result;
        }

        private static byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

        public static string Encrypt(string pToEncrypt, string sKey)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //把字符串放到byte数组中
            byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);

            //建立加密对象的密钥和偏移量
            //使得输入密码必须输入英文文本
            des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
            des.IV = IV;
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            //Write  the  byte  array  into  the  crypto  stream
            //(It  will  end  up  in  the  memory  stream)
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            //Get  the  data  back  from  the  memory  stream,  and  into  a  string
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                //Format  as  hex
                ret.AppendFormat("{0:X2}", b);
            }
            ret.ToString();
            return ret.ToString();
        }

        public static string Decrypt(string pToDecrypt, string sKey)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();

            //Put  the  input  string  into  the  byte  array
            byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
            for (int x = 0; x < pToDecrypt.Length / 2; x++)
            {
                int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
                inputByteArray[x] = (byte)i;
            }

            //建立加密对象的密钥和偏移量，此值重要，不能修改
            des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
            des.IV = IV;
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            //Flush  the  data  through  the  crypto  stream  into  the  memory  stream
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();

            //Get  the  decrypted  data  back  from  the  memory  stream
            //建立StringBuild对象，CreateDecrypt使用的是流对象，必须把解密后的文本变成流对象
            StringBuilder ret = new StringBuilder();

            return System.Text.Encoding.Default.GetString(ms.ToArray());
        }

        public static string CreateMd5(string str)
        {
            string hash = "";
            MD5 md5 = MD5.Create();//实例化一个md5对像
            // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符
                hash = hash + s[i].ToString("X");
            }
            return hash;
        }
    }
}